package org.sais.eswn.net;

import java.awt.Color;
import org.sais.eswn.core.GameCore;
import java.io.*;
import java.net.*;
import javax.swing.JOptionPane;
import org.sais.eswn.core.Player;
import org.sais.eswn.tool.Tools;

abstract public class CommonMessageDispatcher {

    protected Sock mParentSock;

    public CommonMessageDispatcher(Sock parentSock) {
        this.mParentSock = parentSock;
    }

    /**
     * Dispatch common game messages.
     * @param ins
     * @param isOpp For watcher, reverse the side to display.
     * @return  Is message dispatched.
     */
    public boolean commonMessageDispath(String ins, boolean isOpp) {
        String cmd;
        cmd = "$CHAT:";
        if (ins.startsWith(cmd)) {
            core().insertMessage(ins.substring(cmd.length()), isOpp ? Color.RED : Color.BLUE);
            return true;
        }
        cmd = "$WATCHCHAT:";
        if (ins.startsWith(cmd)) {
            if (!ins.substring(cmd.length()).startsWith(mParentSock.getPlayerName())) {
                core().insertMessage(ins.substring(cmd.length()), new Color(120, 60, 0));
            }
            return true;
        }
        cmd = "$PLAYERNAME:";
        if (ins.startsWith(cmd)) {
            core().setPlayerName(isOpp ? Player.OPP : Player.ICH, ins.substring(cmd.length()));
            core().send("$PLAYERNAMERETURN:" + core().getPlayer(isOpp ? Player.ICH : Player.OPP).getName());
            return true;
        }
        cmd = "$PLAYERNAMERETURN:";
        if (ins.startsWith(cmd)) {
            core().setPlayerName(isOpp ? Player.OPP : Player.ICH, ins.substring(cmd.length()));
            return true;
        }
        cmd = "$DECKNAME:";
        if (ins.startsWith(cmd)) {
            if (isOpp) {
                core().setDeckName(Player.OPP, ins.substring(cmd.length()));
            } else {
                core().setDeckName(Player.ICH, ins.substring(cmd.length()));
            }
            return true;
        }
        cmd = "$DECK:";
        if (ins.startsWith(cmd)) {
            if (isOpp) {
                core().setDeckBySockString(Player.OPP, ins.substring(cmd.length()));
            } else {
                core().setDeckBySockString(Player.ICH, ins.substring(cmd.length()));
            }
            return true;
        }
        cmd = "$MOVE:";
        if (ins.startsWith(cmd)) {
            String[] s = ins.substring(cmd.length()).split(" ");
            core().move(Integer.parseInt(s[0]), Integer.parseInt(s[1]), s[2], isOpp ? Player.OPP : Player.ICH);
            core().updateUI(isOpp ? Player.OPP : Player.ICH);
            return true;
        }
        cmd = "$CARDSET:";
        if (ins.startsWith(cmd)) {
            core().setCardSet(true);
            core().insertMessage(Tools.getLoc(23), Color.BLACK);
            return true;
        }
        cmd = "$PLAY:";
        if (ins.startsWith(cmd)) {
            core().setCardSet(true);
            core().setPlay(Player.ICH, false);
            return true;
        }
        cmd = "$PLAYMSG:";
        if (ins.startsWith(cmd)) {
            core().insertMessage(ins.substring(cmd.length()), Color.BLACK);
            return true;
        }

        // For watchers
        int playerIndex = isOpp ? Player.OPP : Player.ICH;
        cmd = "$DECKREMAIN:";
        if (ins.startsWith(cmd)) {
            core().setDeckRemain(playerIndex, ins.substring(cmd.length()));
            return true;
        }
        cmd = "$FIELD:";
        if (ins.startsWith(cmd)) {
            core().setField(playerIndex, ins.substring(cmd.length()));
            return true;
        }
        cmd = "$GRAVE:";
        if (ins.startsWith(cmd)) {
            core().setGrave(playerIndex, ins.substring(cmd.length()));
            return true;
        }
        cmd = "$PHASE:";
        if (ins.startsWith(cmd)) {
            core().setPhase(Integer.parseInt(ins.substring(cmd.length())));
            core().updateUI(playerIndex);
            return true;
        }

        return false;
    }

    abstract public void dispatch(String instr);

    protected GameCore core() {
        return mParentSock.getCore();
    }

    protected Socket soc() {
        return mParentSock.getSocket();
    }

    public boolean send(String message) { //return false when error
        try {
            if (!soc().isConnected()) {
                mParentSock.mSocket = null;
                return false;
            }
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(soc().getOutputStream(), "Unicode"));
            out.write(message);
            out.newLine();
            out.flush();
            return true;
        } catch (SocketException se) {
            se.printStackTrace();
            try {
                JOptionPane.showMessageDialog(null, se.getClass() + "\n" + se.getMessage(), "Send() in MessageDispatcher", JOptionPane.ERROR_MESSAGE);
                soc().close();
                mParentSock.mSocket = null;
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, ex.getClass() + "\n" + ex.getMessage(), "Send() in MessageDispatcher", JOptionPane.ERROR_MESSAGE);
                ex.printStackTrace();
            }
            return false;
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, ex.getClass() + "\n" + ex.getMessage(), "Send() in MessageDispatcher", JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace();
            return false;
        }
    }
}
